package com.sqlcheck.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sqlcheck.common.Result;
import com.sqlcheck.dto.request.CreateScanTaskRequest;
import com.sqlcheck.dto.response.ScanTaskResponse;
import com.sqlcheck.dto.response.ScanResultVO;
import com.sqlcheck.entity.ScanTask;
import com.sqlcheck.entity.ScanResult;
import com.sqlcheck.service.GitRepositoryService;
import com.sqlcheck.repository.ScanResultRepository;
import com.sqlcheck.dto.response.TaskScanResults;
import com.sqlcheck.service.ScanTaskService;
import com.sqlcheck.service.TemporaryCredentialService;
import com.sqlcheck.service.SqlStatementService;
import com.sqlcheck.service.impl.ScanTaskDispatcherServiceImpl;
import com.sqlcheck.dto.request.CreateScanTaskWithCredentialsRequest;
import com.sqlcheck.enums.GitPlatform;
import com.sqlcheck.enums.TaskStatus;
import com.sqlcheck.enums.TaskType;
import io.swagger.v3.oas.annotations.Operation;
import java.util.stream.Collectors;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/scan-tasks")
@RequiredArgsConstructor
@Tag(name = "扫描任务管理", description = "SQL兼容性扫描任务的CRUD操作和状态管理，包括创建任务、查询任务状态、启动/取消任务等功能")
public class ScanTaskController {

    private final ScanTaskService scanTaskService;
    private final ScanResultRepository scanResultRepository;
    private final TemporaryCredentialService temporaryCredentialService;
    private final GitRepositoryService gitRepositoryService;
    private final SqlStatementService sqlStatementService;
    private final ScanTaskDispatcherServiceImpl scanTaskDispatcherService;

    @PostMapping("/with-credentials")
    @Operation(summary = "使用临时凭据创建扫描任务", description = "创建扫描任务并提供临时凭据（个人Token或数据库密码），凭据仅临时存储不持久化")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "任务创建成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "400", description = "请求参数无效"),
            @ApiResponse(responseCode = "401", description = "用户未认证"),
            @ApiResponse(responseCode = "403", description = "权限不足")
    })
    public Result<ScanTaskResponse> createTaskWithCredentials(
            @Valid @RequestBody @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "扫描任务创建请求（包含临时凭据）", required = true, content = @Content(schema = @Schema(implementation = CreateScanTaskWithCredentialsRequest.class))) CreateScanTaskWithCredentialsRequest request,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long userId) {

        log.info("使用临时凭据创建扫描任务: {}, 用户: {}, 授权模式: PERSONAL_TOKEN",
                request.getTaskName(), userId);

        // 转换为标准请求
        CreateScanTaskRequest standardRequest = convertToStandardRequest(request);

        // 创建任务
        ScanTaskResponse response = scanTaskService.createTask(standardRequest, userId);

        // 存储临时凭据
        storeTemporaryCredentials(response.getId(), request);

        return Result.success(response);
    }

    @PostMapping
    @Operation(summary = "创建扫描任务", description = "创建一个新的SQL兼容性扫描任务，支持项目扫描、手动SQL分析、数据库扫描等类型")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "任务创建成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "400", description = "请求参数无效"),
            @ApiResponse(responseCode = "401", description = "用户未认证"),
            @ApiResponse(responseCode = "403", description = "权限不足")
    })
    public Result<ScanTaskResponse> createTask(
            @Valid @RequestBody @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "扫描任务创建请求", required = true, content = @Content(schema = @Schema(implementation = CreateScanTaskRequest.class))) CreateScanTaskRequest request,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long userId) {

        log.info("创建扫描任务请求: {}, 用户: {}", request.getTaskName(), userId);
        ScanTaskResponse response = scanTaskService.createTask(request, userId);
        return Result.success(response);
    }

    @GetMapping("/{taskId}")
    @Operation(summary = "获取任务详情", description = "根据任务ID获取扫描任务的详细信息，包括任务状态、进度、配置等")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<ScanTaskResponse> getTask(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long userId) {
        ScanTaskResponse response = scanTaskService.getTaskById(taskId, userId);
        return Result.success(response);
    }

    @GetMapping("/public/{taskId}")
    @Operation(summary = "公开获取任务详情", description = "公开访问任务详情，不需要用户认证，任何人拿到链接都可以访问")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<ScanTaskResponse> getTaskPublic(
            @Parameter(description = "任务ID", required = true, example = "157") @PathVariable Long taskId) {
        log.info("公开访问任务详情: taskId={}", taskId);
        // 传入null作为currentUserId，跳过权限检查
        ScanTaskResponse response = scanTaskService.getTaskById(taskId, null);
        return Result.success(response);
    }

    @DeleteMapping("/{taskId}")
    @Operation(summary = "删除任务", description = "删除指定的扫描任务，只有任务创建者可以删除")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "删除成功"),
            @ApiResponse(responseCode = "400", description = "任务状态不允许删除"),
            @ApiResponse(responseCode = "403", description = "无权限删除此任务"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<Void> deleteTask(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long userId) {
        log.info("删除扫描任务: taskId={}, 操作用户: {}", taskId, userId);
        scanTaskService.deleteTask(taskId, userId);
        return Result.success();
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "分页获取用户的任务列表", description = "分页查询指定用户创建的所有扫描任务")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功")
    })
    public Result<IPage<ScanTaskResponse>> getUserTasks(
            @Parameter(description = "用户ID", required = true, example = "1") @PathVariable Long userId,
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long currentUserId) {

        Page<ScanTask> page = new Page<>(current, size);
        IPage<ScanTaskResponse> response = scanTaskService.getTasksByUserId(userId, page, currentUserId);
        return Result.success(response);
    }

    @GetMapping("/project/{projectId}")
    @Operation(summary = "获取项目的任务列表", description = "获取指定项目下的所有扫描任务")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "项目不存在")
    })
    public Result<List<ScanTaskResponse>> getProjectTasks(
            @Parameter(description = "项目ID", required = true, example = "1") @PathVariable Long projectId,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long currentUserId) {
        List<ScanTaskResponse> response = scanTaskService.getTasksByProjectId(projectId, currentUserId);
        return Result.success(response);
    }

    @PutMapping("/{taskId}/status")
    @Operation(summary = "更新任务状态", description = "更新扫描任务的执行状态和进度，通常由扫描引擎调用")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "更新成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "400", description = "状态值无效"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<ScanTaskResponse> updateTaskStatus(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId,
            @Parameter(description = "任务状态", required = true, schema = @Schema(allowableValues = { "PENDING", "RUNNING",
                    "SUCCESS", "FAILED", "CANCELLED" })) @RequestParam String status,
            @Parameter(description = "任务进度(0-100)", example = "50") @RequestParam(required = false) Integer progress) {

        TaskStatus taskStatus = TaskStatus.valueOf(status);
        ScanTaskResponse response = scanTaskService.updateTaskStatus(taskId, taskStatus, progress);
        return Result.success(response);
    }

    @PutMapping("/{taskId}/error")
    @Operation(summary = "设置任务错误信息", description = "当任务执行失败时，设置详细的错误信息")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "设置成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<ScanTaskResponse> updateTaskError(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId,
            @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "错误信息", required = true, content = @Content(schema = @Schema(implementation = String.class, example = "扫描过程中发生网络超时"))) @RequestBody String errorMessage) {

        ScanTaskResponse response = scanTaskService.updateTaskError(taskId, errorMessage);
        return Result.success(response);
    }

    @PostMapping("/{taskId}/start")
    @Operation(summary = "启动任务", description = "启动一个待执行的扫描任务，立即返回启动结果，任务将异步执行")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "任务启动成功，已进入异步执行队列"),
            @ApiResponse(responseCode = "400", description = "任务状态不允许启动或配置有误"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<Map<String, Object>> startTask(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId,
            HttpSession session) {

        try {
            log.info("收到启动任务请求: taskId={}", taskId);

            // 快速验证任务状态和获取任务信息
            ScanTask task = scanTaskService.getTaskByIdInternal(taskId);
            log.info("任务基本信息: taskId={}, taskType={}, status={}", taskId, task.getTaskType(),
                    task.getStatus());

            // 检查任务状态是否允许启动,允许失败任务重新启动
            if (!TaskStatus.PENDING.equals(task.getStatus()) &&
                    !TaskStatus.FAILED.equals(task.getStatus())) {
                String errorMsg = "任务状态不允许启动，当前状态: " + task.getStatus();
                log.warn("任务启动失败: taskId={}, reason={}", taskId, errorMsg);
                return Result.error(errorMsg);
            }

            // 预先验证关键配置（快速验证，不耗时操作）
            if (TaskType.GIT_SOURCE_SCAN.equals(task.getTaskType())) {
                String platformName = extractGitPlatformFromConfig(task.getConfig());
                if (platformName != null) {
                    try {
                        GitPlatform platform = GitPlatform.valueOf(platformName.toUpperCase());
                        // 只检查token是否存在，不进行网络验证
                        String accessToken = temporaryCredentialService.getGitToken(taskId, platform);
                        if (accessToken == null || accessToken.trim().isEmpty()) {
                            String errorMsg = "个人访问令牌不存在或已过期，请重新设置Token";
                            log.warn("任务启动失败: taskId={}, reason={}", taskId, errorMsg);
                            scanTaskService.updateTaskError(taskId, errorMsg);
                            return Result.error(errorMsg);
                        }
                    } catch (IllegalArgumentException e) {
                        String errorMsg = "不支持的Git平台: " + platformName;
                        log.warn("任务启动失败: taskId={}, reason={}", taskId, errorMsg);
                        scanTaskService.updateTaskError(taskId, errorMsg);
                        return Result.error(errorMsg);
                    }
                }
            }

            // 立即更新任务状态为RUNNING并返回响应
            scanTaskService.startTask(taskId);
            log.info("任务状态已更新为RUNNING: taskId={}", taskId);

            // 异步提交任务到执行队列（立即返回，不等待执行完成）
            try {
                String accessToken = null;

                // 重新获取token（因为任务可能需要）
                if (TaskType.GIT_SOURCE_SCAN.equals(task.getTaskType())) {
                    String platformName = extractGitPlatformFromConfig(task.getConfig());
                    if (platformName != null) {
                        GitPlatform platform = GitPlatform.valueOf(platformName.toUpperCase());
                        accessToken = temporaryCredentialService.getGitToken(taskId, platform);
                    }
                }

                // 异步执行（不阻塞响应）
                scanTaskDispatcherService.executeTask(task, accessToken);
                log.info("任务已提交到异步执行队列: taskId={}", taskId);

            } catch (Exception asyncException) {
                // 异步提交失败，记录错误但不影响响应
                log.error("任务异步提交失败，将在后台重试: taskId={}", taskId, asyncException);
                // 可以考虑在这里实现重试机制或者更新任务状态
                scanTaskService.updateTaskError(taskId, "任务提交到执行队列失败: " + asyncException.getMessage());
            }

            // 构造成功响应
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("taskId", taskId);
            responseData.put("status", "RUNNING");
            responseData.put("message", "任务已成功启动，正在后台执行");
            responseData.put("timestamp", System.currentTimeMillis());

            log.info("任务启动请求处理完成: taskId={}", taskId);
            return Result.success(responseData);

        } catch (Exception e) {
            log.error("任务启动过程发生异常: taskId={}", taskId, e);
            try {
                // 尝试更新任务错误状态
                scanTaskService.updateTaskError(taskId, "任务启动失败: " + e.getMessage());
            } catch (Exception updateError) {
                log.error("更新任务错误状态失败: taskId={}, updateError={}", taskId, updateError.getMessage());
            }
            return Result.error("任务启动失败: " + e.getMessage());
        }
    }

    @PostMapping("/{taskId}/cancel")
    @Operation(summary = "取消任务", description = "取消一个正在执行或待执行的扫描任务")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "取消成功"),
            @ApiResponse(responseCode = "400", description = "任务状态不允许取消"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<Void> cancelTask(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId) {

        // 获取任务信息
        // 取消任务时不检查权限，允许系统内部调用
        ScanTaskResponse taskResponse = scanTaskService.getTaskById(taskId, null);

        // 统一使用scanTaskService的取消方法
        scanTaskService.cancelTask(taskId);

        // 如果是Git相关任务，需要额外清理Git资源
        if ("GIT_SOURCE_SCAN".equals(taskResponse.getTaskType())) {
            try {
                gitRepositoryService.cleanupGitResources(taskId);
            } catch (Exception e) {
                log.warn("清理Git资源失败: taskId={}", taskId, e);
            }
        }

        return Result.success();
    }

    @PostMapping("/{taskId}/retry")
    @Operation(summary = "重试失败的任务", description = "重试一个执行失败的扫描任务，只有FAILED状态的任务可以重试")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "重试成功", content = @Content(schema = @Schema(implementation = ScanTaskResponse.class))),
            @ApiResponse(responseCode = "400", description = "任务状态不允许重试或已达到最大重试次数"),
            @ApiResponse(responseCode = "403", description = "无权限操作此任务"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<Map<String, Object>> retryTask(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId,
            @Parameter(description = "当前用户ID", required = true, example = "1") @RequestHeader("X-User-ID") Long userId) {

        log.info("重试任务: taskId={}, 操作用户: {}", taskId, userId);

        try {
            // 第一步：重置任务状态为PENDING并增加重试次数
            ScanTaskResponse taskResponse = scanTaskService.retryTask(taskId, userId);
            log.info("任务状态已重置: taskId={}, status={}", taskId, taskResponse.getStatus());

            // 第二步：立即启动任务执行（类似startTask的逻辑）
            // 预先验证关键配置
            if ("GIT_SOURCE_SCAN".equals(taskResponse.getTaskType())) {
                String platformName = extractGitPlatformFromConfig(taskResponse.getConfig());
                if (platformName != null) {
                    try {
                        GitPlatform platform = GitPlatform.valueOf(platformName.toUpperCase());
                        // 检查token是否存在
                        String accessToken = temporaryCredentialService.getGitToken(taskId, platform);
                        if (accessToken == null || accessToken.trim().isEmpty()) {
                            String errorMsg = "个人访问令牌不存在或已过期，无法重试任务";
                            log.warn("任务重试失败: taskId={}, reason={}", taskId, errorMsg);
                            scanTaskService.updateTaskError(taskId, errorMsg);
                            return Result.error(errorMsg);
                        }
                    } catch (IllegalArgumentException e) {
                        String errorMsg = "不支持的Git平台: " + platformName;
                        log.warn("任务重试失败: taskId={}, reason={}", taskId, errorMsg);
                        scanTaskService.updateTaskError(taskId, errorMsg);
                        return Result.error(errorMsg);
                    }
                }
            }

            // 第三步：启动任务并异步执行
            scanTaskService.startTask(taskId);
            log.info("任务已启动: taskId={}", taskId);

            // 异步提交任务到执行队列
            try {
                ScanTask task = buildScanTaskFromResponse(taskResponse);
                String accessToken = null;

                // 获取访问令牌（如果需要）
                if ("GIT_SOURCE_SCAN".equals(taskResponse.getTaskType())) {
                    String platformName = extractGitPlatformFromConfig(taskResponse.getConfig());
                    if (platformName != null) {
                        GitPlatform platform = GitPlatform.valueOf(platformName.toUpperCase());
                        accessToken = temporaryCredentialService.getGitToken(taskId, platform);
                    }
                }

                // 异步执行任务
                scanTaskDispatcherService.executeTask(task, accessToken);
                log.info("重试任务已提交到异步执行队列: taskId={}", taskId);

            } catch (Exception asyncException) {
                // 异步提交失败，更新任务状态
                log.error("重试任务异步提交失败: taskId={}", taskId, asyncException);
                scanTaskService.updateTaskError(taskId, "重试任务提交到执行队列失败: " + asyncException.getMessage());
                return Result.error("重试任务提交失败: " + asyncException.getMessage());
            }

            // 构造成功响应
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("taskId", taskId);
            responseData.put("status", "RUNNING");
            responseData.put("message", "任务重试成功，正在后台执行");
            responseData.put("retryCount", taskResponse.getRetryCount());
            responseData.put("maxRetryCount", taskResponse.getMaxRetryCount());
            responseData.put("timestamp", System.currentTimeMillis());

            log.info("任务重试请求处理完成: taskId={}", taskId);
            return Result.success(responseData);

        } catch (Exception e) {
            log.error("任务重试过程发生异常: taskId={}", taskId, e);
            return Result.error("任务重试失败: " + e.getMessage());
        }
    }

    @GetMapping("/{taskId}/check-credentials")
    @Operation(summary = "检查任务凭证有效期", description = "检查指定任务的用户凭证是否仍然有效")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "检查成功"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<Map<String, Object>> checkTaskCredentials(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId) {
        Map<String, Object> credentialStatus = scanTaskService.checkTaskCredentials(taskId);
        return Result.success(credentialStatus);
    }

    @GetMapping("/{taskId}/can-retry")
    @Operation(summary = "检查任务是否可重试", description = "检查指定任务是否处于可重试状态")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "检查成功"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<Map<String, Object>> canRetryTask(
            @Parameter(description = "任务ID", required = true, example = "1") @PathVariable Long taskId) {

        boolean canRetry = scanTaskService.canRetry(taskId);
        // 检查重试状态时不检查权限，允许系统内部调用
        ScanTaskResponse task = scanTaskService.getTaskById(taskId, null);

        Map<String, Object> result = new HashMap<>();
        result.put("canRetry", canRetry);
        result.put("currentRetryCount", task.getRetryCount() != null ? task.getRetryCount() : 0);
        result.put("maxRetryCount", task.getMaxRetryCount() != null ? task.getMaxRetryCount() : 3);
        result.put("status", task.getStatus());

        return Result.success(result);
    }

    @GetMapping("/running")
    @Operation(summary = "获取正在执行的任务", description = "获取当前系统中所有状态为RUNNING的扫描任务列表")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功")
    })
    public Result<List<ScanTaskResponse>> getRunningTasks() {
        List<ScanTaskResponse> response = scanTaskService.getRunningTasks();
        return Result.success(response);
    }

    @GetMapping("/{taskId}/results")
    @Operation(summary = "获取任务扫描结果", description = "返回指定任务的扫描统计信息与问题列表")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<TaskScanResults> getTaskResults(
            @Parameter(description = "任务ID", required = true, example = "13") @PathVariable Long taskId) {

        // 验证任务存在
        // 获取扫描结果时不检查权限，允许系统内部调用
        ScanTaskResponse task = scanTaskService.getTaskById(taskId, null);
        if (task == null) {
            return Result.error("任务不存在");
        }

        // 查询结果
        List<ScanResult> list = scanResultRepository.findByTaskId(taskId);

        TaskScanResults dto = new TaskScanResults();
        dto.setTotalFiles((int) list.stream().map(ScanResult::getFilePath).distinct().count());
        // 修复：从SqlStatement表统计真实的SQL语句数量，而不是从ScanResult统计
        int actualSqlStatementsCount = sqlStatementService.getStatementsByTask(taskId).size();
        dto.setSqlStatements(actualSqlStatementsCount);

        // 计算有问题的SQL语句数量
        int problemSqlStatementsCount = (int) list.stream()
                .filter(r -> r.getStatementNumber() != null)
                .map(ScanResult::getStatementNumber)
                .distinct()
                .count();
        dto.setProblemSqlStatements(problemSqlStatementsCount);

        // 转换结果，gitFileUrl由GitTaskExecutionService在Git任务中动态生成并存储到metadata
        List<ScanResultVO> issues = list.stream()
                .map(ScanResultVO::fromScanResult)
                .collect(Collectors.toList());
        dto.setIssues(issues);

        return Result.success(dto);
    }

    /**
     * 构建ScanTask实体从ScanTaskResponse
     */
    private ScanTask buildScanTaskFromResponse(ScanTaskResponse response) {
        ScanTask task = new ScanTask();
        task.setId(response.getId());
        task.setTaskName(response.getTaskName());
        task.setTaskType(TaskType.valueOf(response.getTaskType()));
        task.setConfigJson(convertMapToJson(response.getConfig()));
        task.setDescription(response.getDescription());
        task.setUserId(response.getUserId());
        task.setProjectId(response.getProjectId());

        // 设置状态信息
        if (response.getStatus() != null) {
            task.setStatus(TaskStatus.valueOf(response.getStatus()));
        }
        task.setProgress(response.getProgress());
        task.setErrorMessage(response.getErrorMessage());

        return task;
    }

    /**
     * 将Map配置转换为JSON字符串
     */
    private String convertMapToJson(Map<String, Object> config) {
        try {
            if (config == null) {
                return "{}";
            }
            return new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(config);
        } catch (Exception e) {
            log.warn("转换配置为JSON失败", e);
            return "{}";
        }
    }

    /**
     * 转换为标准任务创建请求
     */
    private CreateScanTaskRequest convertToStandardRequest(CreateScanTaskWithCredentialsRequest request) {
        CreateScanTaskRequest standardRequest = new CreateScanTaskRequest();
        standardRequest.setTaskName(request.getTaskName());
        standardRequest.setTaskType(request.getTaskType());
        standardRequest.setProjectId(request.getProjectId());
        standardRequest.setBranchName(request.getBranchName());
        standardRequest.setDescription(request.getDescription());

        // 复制配置并添加授权模式信息
        Map<String, Object> config = request.getConfig();
        if (config == null) {
            config = new HashMap<>();
        } else {
            config = new HashMap<>(config);
        }

        // 从config中提取数据库类型并设置到顶级字段
        String sourceDbType = (String) config.get("sourceDbType");
        String targetDbType = (String) config.get("targetDbType");
        if (sourceDbType != null) {
            standardRequest.setSourceDbType(sourceDbType);
        }
        if (targetDbType != null) {
            standardRequest.setTargetDbType(targetDbType);
        }

        // 从config中提取AI增强配置并设置到顶级字段
        Boolean aiEnhancementEnabled = (Boolean) config.get("aiEnhancementEnabled");
        if (aiEnhancementEnabled != null) {
            standardRequest.setAiEnhancementEnabled(aiEnhancementEnabled);
        }

        // AI筛选配置将由全局配置自动处理，这里只需要传递开关状态

        // 同时设置AI增强标志从顶级字段
        if (request.getAiEnhancementEnabled() != null) {
            standardRequest.setAiEnhancementEnabled(request.getAiEnhancementEnabled());
        }

        if (request.getGitPlatform() != null) {
            config.put("gitPlatform", request.getGitPlatform().name().toLowerCase());
        }
        if (request.getGitRepositoryUrl() != null) {
            config.put("repositoryUrl", request.getGitRepositoryUrl());
        }

        // 添加分析引擎配置
        if (request.getAnalysisEngine() != null) {
            config.put("analysisEngine", request.getAnalysisEngine());
        }

        // 添加数据库相关配置
        if (Boolean.TRUE.equals(request.getEnableDatabaseScan())) {
            config.put("enableDatabaseScan", true);
            if (request.getDatabaseHost() != null) {
                config.put("databaseHost", request.getDatabaseHost());
            }
            if (request.getDatabasePort() != null) {
                config.put("databasePort", request.getDatabasePort());
            }
            if (request.getDatabaseName() != null) {
                config.put("databaseName", request.getDatabaseName());
            }
            if (request.getDatabaseUsername() != null) {
                config.put("databaseUsername", request.getDatabaseUsername());
            }
            if (request.getDatabaseSchema() != null) {
                config.put("databaseSchema", request.getDatabaseSchema());
            }
            if (request.getDatabaseVersion() != null) {
                config.put("databaseVersion", request.getDatabaseVersion());
                config.put("databaseVersionAutoDetected", true); // 标记版本是自动检测的
            }
            if (request.getDdlExtractionOptions() != null) {
                Map<String, Object> ddlOptions = new HashMap<>();
                CreateScanTaskWithCredentialsRequest.DDLExtractionOptions options = request.getDdlExtractionOptions();
                ddlOptions.put("includeViews", options.getIncludeViews());
                ddlOptions.put("includeIndexes", options.getIncludeIndexes());
                ddlOptions.put("includeConstraints", options.getIncludeConstraints());
                ddlOptions.put("targetTables", options.getTargetTables());
                config.put("ddlExtractionOptions", ddlOptions);
            }
        }

        standardRequest.setConfig(config);
        log.info("最终配置: {}", config);
        return standardRequest;
    }

    /**
     * 存储临时凭据
     */
    private void storeTemporaryCredentials(Long taskId, CreateScanTaskWithCredentialsRequest request) {
        int expirationMinutes = request.getCredentialExpirationMinutes() != null
                ? request.getCredentialExpirationMinutes()
                : 60;

        // 存储Git Token
        if (request.getPersonalAccessToken() != null
                && !request.getPersonalAccessToken().trim().isEmpty()) {

            GitPlatform platform = request.getGitPlatform() != null ? request.getGitPlatform() : GitPlatform.GITLAB;

            temporaryCredentialService.storeGitToken(
                    taskId, platform, request.getPersonalAccessToken(), expirationMinutes);
        }

        // 存储数据库密码
        if (Boolean.TRUE.equals(request.getEnableDatabaseScan())
                && request.getDatabasePassword() != null
                && !request.getDatabasePassword().trim().isEmpty()) {

            temporaryCredentialService.storeDatabasePassword(
                    taskId, request.getDatabasePassword(), expirationMinutes);
        }
    }

    /**
     * 从任务配置中提取Git平台信息
     */
    private String extractGitPlatformFromConfig(Map<String, Object> config) {
        try {
            if (config == null) {
                return null;
            }

            Object gitPlatform = config.get("gitPlatform");
            return gitPlatform != null ? gitPlatform.toString() : null;

        } catch (Exception e) {
            log.warn("解析任务配置中的Git平台信息失败: {}", e.getMessage());
            return null;
        }
    }

    @GetMapping("/{taskId}/sql-statements")
    @Operation(summary = "获取任务SQL语句列表", description = "返回指定任务扫描过程中提取的SQL语句详细信息")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<List<com.sqlcheck.entity.SqlStatement>> getTaskSqlStatements(
            @Parameter(description = "任务ID", required = true, example = "13") @PathVariable Long taskId) {

        // 验证任务存在
        ScanTaskResponse task = scanTaskService.getTaskById(taskId, null);
        if (task == null) {
            return Result.error("任务不存在");
        }

        // 获取SQL语句列表
        List<com.sqlcheck.entity.SqlStatement> statements = sqlStatementService.getStatementsByTask(taskId);

        log.info("获取任务SQL语句: taskId={}, 语句数量={}", taskId, statements.size());
        return Result.success(statements);
    }

    @GetMapping("/{taskId}/sql-statements-with-issues")
    @Operation(summary = "获取任务SQL语句列表（包含问题统计）", description = "返回指定任务扫描过程中提取的SQL语句及其关联的问题统计信息")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<List<com.sqlcheck.dto.response.SqlStatementVO>> getTaskSqlStatementsWithIssues(
            @Parameter(description = "任务ID", required = true, example = "13") @PathVariable Long taskId) {

        // 验证任务存在
        ScanTaskResponse task = scanTaskService.getTaskById(taskId, null);
        if (task == null) {
            return Result.error("任务不存在");
        }

        // 调用SqlStatementController的逻辑获取带问题统计的SQL语句列表
        List<com.sqlcheck.dto.response.SqlStatementVO> statementsWithIssues = sqlStatementService
                .getStatementsWithIssuesByTask(taskId);

        log.info("获取任务SQL语句（含问题统计）: taskId={}, 语句数量={}", taskId, statementsWithIssues.size());
        return Result.success(statementsWithIssues);
    }
}